from django.shortcuts import render, redirect

from django.views.generic import View

from goods.models import GoodsSKU,GoodsCategory,IndexGoodsBanner,IndexPromotionBanner,IndexCategoryGoodsBanner

from django.core.cache import cache

from django_redis import get_redis_connection

from django.core.urlresolvers import reverse

from django.core.paginator import Paginator, EmptyPage

import json
# Create your views here.


'''购物车逻辑封装到基类中'''
class BaseCartView(View):

    # 提供购物车数据的统计功能
    def get_cart_num(self, request):

        cart_num = 0

        # 如果用户登录，就从redis中获取购物车数据
        if request.user.is_authenticated():
            # 登陆用户的数据存储在redis中
            redis_conn = get_redis_connection('default')

            user_id = request.user.id

            # 从redis中获取购物车的数据,返回字典, key和value都是bytes类型
            cart_dict = redis_conn.hgetall('cart_%s' % user_id)

            # 遍历字典,累加购物车的值
            for val in cart_dict.values():
                cart_num += int(val)

        else:
            # 如果用户未登录，就从cookie中获取购物车数据
            # cart_json 是字符串类型的
            cart_json = request.COOKIES.get('cart')

            # 判断购物车数据是否存在
            if cart_json is not None:
                # 转成字典
                cart_dict = json.loads(cart_json)
            else:
                cart_dict = {}

            # 遍历
            for val in cart_dict.values():

                cart_num += val

        return cart_num





'''商品列表页面展示'''
# 不需要用户登陆即可访问
class ListView(BaseCartView):

    def get(self, request, category_id, page_num):
        # category_id是展示哪一类商品的列表
        # page_num是展示第几页

        # 读取排序规则:当用户没有传入sort时，指定为默认排序
        sort = request.GET.get('sort', 'default')

        '''获取请求参数'''
        # 查询用户要看的商品分类category对象
        try:
            category = GoodsCategory.objects.get(id=category_id)
        except GoodsCategory.DoesNotExist:
            return redirect(reverse('goods:index'))

        # 查询全部商品分类
        categorys = GoodsCategory.objects.all()

        # 查询新品推荐
        new_skus = GoodsSKU.objects.filter(category=category).order_by('-create_time')[:2]

        '''实现排序'''
        # 查询所有category关联的sku，并完成排序
        if sort == 'price':
            # 以价格从低到高排序
            skus = GoodsSKU.objects.filter(category=category).order_by('price')
        elif sort == 'hot':
            # 以人气从高到低排序
            skus = GoodsSKU.objects.filter(category=category).order_by('-sales')
        else:
            skus = GoodsSKU.objects.filter(category=category)

            # 重置sort，防止sort超出范围
            sort = 'default'

        '''实现分页:对skus分页， 每页2个GoodsSKU模型对象'''
        paginator = Paginator(skus, 2)

        # 获取用户要看的那一页数据
        page_num = int(page_num)

        # 每页2个GoodsSKU模型对象
        try:
            page_skus = paginator.page(page_num)
        except EmptyPage:
            page_skus = paginator.page(1)

        # 获取页码数列表信息，再传给模板，就不用在模板中获取
        page_list = paginator.page_range

        # 构造上下文
        context = {
            'category': category,
            'categorys': categorys,
            'new_skus': new_skus,
            'page_skus': page_skus,  #只需要传入分页后的sku信息
            'page_list': page_list,
            'sort': sort

        }



        return render(request, 'list.html', context)










'''展示商品详情页面'''
class DetailView(BaseCartView):

    def get(self, request, sku_id):

        # 查询商品的sku信息
        try:
            sku = GoodsSKU.objects.get(id=sku_id)
        except GoodsSKU.DoesNotExist:
            return redirect(reverse('goods: index'))

        # 查询商品的分类信息
        categorys = GoodsCategory.objects.all()

        # 从订单中获取评论信息
        sku_orders = sku.ordergoods_set.all().order_by('-create_time')[:30]
        if sku_orders:
            for sku_order in sku_orders:
                sku_order.ctime = sku_order.create_time.strftime('%Y-%m-%d %H:%M:%S')
                sku_order.username = sku_order.order.user.username
        else:
            sku_orders = []

        # 查询新品推荐：最新发布的两件商品
        new_skus = GoodsSKU.objects.filter(category=sku.category).order_by('-create_time')[:2]

        # 查询以其他规格销售的商品：
        other_skus = sku.goods.goodssku_set.exclude(id=sku_id)

        # 查询购物车的数据
        # 查询购物车信息：购物车的数据不被缓存，每个用户的信息不同
        cart_num = 0

        '''
        获取主页购物车的信息
            购物车的数据存储在redis中，数据类型是hash
            (key filed value) cart_userid sku_1 10 sku_2 20
        '''
        # 只有登录的用户才会有购物车的数据
        if request.user.is_authenticated():

            # 创建redis_conn对象
            redis_conn = get_redis_connection('default')

            # 获取用户的id
            user_id = request.user.id

            # 从redis中获取购物车数据， 返回字典, 字典的key和value是字节类型(bytes)
            cart_dict = redis_conn.hgetall('cart_%s' % user_id)

            # 遍历购物车字典的value，累加求和
            for value in cart_dict.values():
                cart_num += int(value)

            '''浏览记录'''#在商品详情页需要实现存储浏览记录的逻辑
            # 浏览记录存储在redis中，之前已经在用户中心界面实现了浏览记录的读取

            ''''''
            # 需要先去重
            redis_conn.lrem('history_%s' % user_id, 0, sku_id)

            # 记录用户浏览信息
            redis_conn.lpush('history_%s' % user_id, sku_id)

            # 最多存储5个
            redis_conn.ltrim('history_%s' % user_id, 0, 4)


        context = {

            'sku':sku,
            'categorys':categorys,
            'sku_orders':sku_orders,
            'new_skus':new_skus,
            'other_skus':other_skus,
            'cart_num':cart_num
        }

        # 更新购物车数据
        context.update(cart_num=cart_num)

        return render(request, 'detail.html', context)




'''展示主页面'''
class IndexView(BaseCartView):

    def  get(self, request):


        '''
        设置缓存：先检查是否有缓存，如果有缓存直接读取缓存数据，没有缓存就查询数据库，然后缓存

        '''

        '''检查是否有缓存数据：尝试获取缓存数据'''
        context = cache.get('index_page_data')

        '''如果没有缓存数据，查询数据'''
        if context is None:

            print('没有缓存数据，查询数据库')
            # 查询用户个人信息,request中包含

            # 查询商品分类信息
            categorys = GoodsCategory.objects.all()

            # 查询图片轮播信息，默认index从小到大
            goods_banners = IndexGoodsBanner.objects.all().order_by('index')

            # 查询促销活动信息，默认index从小到大排许
            promotion_banners = IndexPromotionBanner.objects.all().order_by('index')

            # 查询商品分类列表信息
            for category in categorys:

                '''以图片展示的商品'''
                image_banners = IndexCategoryGoodsBanner.objects.filter(category=category, display_type=1)
                category.image_banners = image_banners

                '''以标题展示的商品'''
                title_banners = IndexCategoryGoodsBanner.objects.filter(category=category, display_type=0)
                category.title_banners = title_banners


            # '''以标题展示的商品'''
            # title_list = []
            #
            # '''以图片展示的商品'''
            # image_list = []
            #
            # for category in categorys:
            #     '''标题'''
            #     title_banner = IndexCategoryGoodsBanner.objects.filter(category=category, display_type=0)
            #
            #     title_list.append(title_banner)
            #
            #
            #     # 图片
            #     image_banner = IndexCategoryGoodsBanner.objects.filter(category=category, display_type=1)
            #
            #     image_list.append(image_banner)


            context = {

                'categorys': categorys,
                'goods_banners': goods_banners,
                'promotion_banners': promotion_banners,
                # 'title_list': title_list,
                # 'image_list': image_list
                # 'cart_num': cart_num

            }

            '''设置缓存： cache.set('key', 缓存的内容， 超时时间）'''
            cache.set('index_page_data', context, 3600)

        # 查询购物车信息：购物车的数据不被缓存，每个用户的信息不同
        cart_num = 0

        '''
        获取主页购物车的信息
            购物车的数据存储在redis中，数据类型是hash
            (key filed value) cart_userid sku_1 10 sku_2 20
        '''
        # 只有登录的用户才会有购物车的数据
        if request.user.is_authenticated():

            # 创建redis_conn对象
            redis_conn = get_redis_connection('default')

            # 获取用户的id
            user_id = request.user.id

            # 从redis中获取购物车数据， 返回字典, 字典的key和value是字节类型(bytes)
            cart_dict = redis_conn.hgetall('cart_%s' % user_id)

            # 遍历购物车字典的value，累加求和
            for value in cart_dict.values():

                cart_num += int(value)


        # 补充购物车数据到缓存中
        context.update(cart_num=cart_num)

        return render(request, 'index.html', context)